'use strict'

process.chdir(__dirname);

const Titbit = require('titbit');
const fs = require('fs');

//导入gohttp
const {httpcli} = require('gohttp');

//导入appid以及appsecret
const wxkey = require('./wxkey.js');

//使用fs封装好的PromiseAPI
const fsp = fs.promises;

//导入数据库的连接实例
const db = require('./initdb.js');

//检测服务是否存在upload文件夹，如果没有，就创建
try {
    fs.accessSync('./upload');
} catch (error) {
    fs.mkdirSync('./upload');
}

const app = new Titbit({
    debug:true//开启调试模式，会输出错误信息，并且输出路由表
});

let _aeskey = ('6sdfs27789fsa0v530af12512dsaf456aiuoy7cbxsf671g85f6934sg8nc134juy3dsa902').substring(5,37);

app.get('/sl-login/:code',async ctx => {
    //获取微信小程序wx.login的授权登录码
    let code = ctx.param.code;
    //使用queryString的形式拼接请求的url地址
    let url = `https://api.weixin.qq.com/sns/jscode2session?appid=${wxkey.appid}&secret=${wxkey.secret}&js_code=${code}&grant_type=authorization_code`;
    //可以通过安装扩展发起请求 npm i gohttp
    //发起请求，获取用户信息
    let ret = await httpcli.get(url);
    
    if(!ret.ok) {
        return ctx.status(500).send('request failed!');
    }
    
    let r = ret.json();

    //设置需要返回的数据并且将数据进行加密
    let data = {
        openid:r.openid,
        login_time:Date.now()
    }

    ctx.send(ctx.helper.aesEncrypt(JSON.stringify(data),_aeskey));
});

//检测加密信息并解密验证
app.get('/token-test',async ctx => {
    let token = ctx.headers.authorization;

    try {
        let data = ctx.helper.aesDecrypt(token,_aeskey);
        ctx.send(data);
    } catch (error) {
        ctx.status(400).send(error.message);
    }
});

//体验中间件
// app.use(async (ctx , next) => {
//     console.log("request",ctx.method,ctx.path,ctx.routerPath);
//     await next();
//     console.log("end request");
// });

// app.use(async (ctx , next) => {
//     console.log("center request");
//     if(ctx.query.say !== 'hello') {
//         console.log("failed check query");
//         return ctx.status(403).send("please say!");
//     }
//     await next();
//     console.log("end center request");
// });

// app.use(async (ctx , next) => {
//     console.log("last request");
//     await next();
//     console.log("end last request");
// });

//添加路由
app.get('/',async ctx => {
    ctx.send('sucess');
});

app.put('/update',async ctx => {
    ctx.send(ctx.body);
});

app.post('/upload',async ctx => {
    //上传图片的所有信息，都被封装在了ctx.files中
    console.log(ctx.files)
    //读取文件对象，默认返回第一个
    let imgfile = ctx.getFile('image')
    if(!imgfile) {
        return ctx.status(400).send('image not found');
    }

    //更改文件名称，确保服务器中文件名称不会重复，不会出现被替换的情况
    let filename = ctx.helper.makeName(imgfile.filename)

    //将文件保存到服务器上，将文件移动到服务器的文件夹中
    await ctx.moveFile(imgfile,`./upload/${filename}`);

    ctx.send(filename)
});

app.post('/content',async ctx => {
    
     
    //将数据以文件的形式保存
    //1.创建文件，设置文件名称
    // let filename = ctx.helper.makeName() + '.json';
    //2.引用API将数据写入文件中
    // await fsp.writeFile(`./files/${filename}`,ctx.rawBody);
    // ctx.send(filename);


    //将数据保存在数据库中
    //1.获取数据（数据需要是json格式）
    let data = JSON.parse(ctx.rawBody.toString('utf8'))

    // 2、将数据保存再数据库中（在数据库中插入一条数据）
    // 2.1 拼写插入的SQL语句
    let sql = `INSERT INTO hs.content` +
        `(id,title,detail,create_time,update_time)` +
        `VALUES ($1,$2,$3,$4,$5) RETURNING id,title`

    // 2.2 根据$n的参数描述 构造参数
    let tm = Date.now()
    let args = [
        // 生成一个不定长的唯一值
        Math.random().toString(16).substring(2, 12),
        data.title,
        data.content,
        tm,
        tm
    ]

    // 2.3 执行SQL语句
    // SQL语句执行成功后会有两个很重要的属性：
    // rows是一个数组
    // rowCount是数字：表示返回的数据或更改的数据条目数量
    let ret = await db.query(sql, args)

    // 3 将执行结果返回
    ctx.send(ret.rows[0])
});

//获取文章列表 ---GET--- /content
app.get('/content',async ctx => {
    let sql = `SELECT id,title,create_time FROM hs.content ORDER BY create_time DESC`;

    let ret = await db.query(sql);

    ctx.send(ret.rows)
})

app.get('/image/:name',async ctx => {
    //:name解析到ctx.param.name（图片的名称）
    let filename = `./upload/${ctx.param.name}`;
    //pipe是对nodejs 流stream 的处理
    //ctx.reply指向了response
    try {
        await ctx.helper.pipe(filename,ctx.reply);
    } catch (error) {
        ctx.status(404);
    }
});

//根据id值获取文章详情
app.get('/content/:id', async ctx => {
    //准备sql
    let sql = `SELECT * FROM hs.content WHERE id=$1`;
    //执行sql db.query(string,[Array])
    let ret = await db.query(sql,[ctx.param.id]);
    //返回信息
    if(ret.rowCount > 0) {
        return ctx.send(ret.rows[0]);
    }
    else{
        return ctx.status(404).send("ERROR! Illegal id!");
    }
});

app.delete('/content/:id',async ctx => {
    let sql = `DELETE FROM hs.content WHERE id=$1`;

    let ret = await db.query(sql,[ctx.param.id]);

    if(ret.rowCount > 0) {
        return ctx.send(ret);
    }
    else{
        return ctx.status(400).send("ERROR! failed to deleted!");
    }
});

app.run(8080);

//MVC  -  Model(数据库/文件系统)  View(视图)  Controller(控制器-处理逻辑)
//MVVM  -  Model  View  viewmodel